﻿using static System.Math;

namespace GeoFits
{
    /// <summary>
    /// 几何图形类：点
    /// </summary>
    public class Point : Geometry
    {
        /// <summary>
        /// 点构造函数
        /// </summary>
        /// <param name="x">点X坐标</param>
        /// <param name="y">点Y坐标</param>
        /// <param name="z">点Z坐标</param>
        public Point(double x, double y, double z)
        { X = x; Y = y; Z = z; }
        /// <summary>
        /// 构造一个默认的点
        /// </summary>
        /// <remarks>点的默认值为：(0, 0, 0)</remarks>
        public Point()
        { X = 0; Y = 0; Z = 0; }
        /// <summary>
        /// 两点间的距离
        /// </summary>
        /// <param name="pt">第二个点</param>
        /// <returns>两点间的距离</returns>
        public double DistanceTo(Point pt)
        {
            return Sqrt((X - pt.X) * (X - pt.X) + (Y - pt.Y) * (Y - pt.Y) + (Z - pt.Z) * (Z - pt.Z));
        }
        /// <summary>
        /// 判断两个向量是指定精度下是否相等
        /// </summary>
        /// <param name="pt">第二个点</param>
        /// <param name="precision">精度</param>
        /// <returns>相等返回true，不相等返回false</returns>
        public bool IsEqual(Point pt, double precision)
        {
            bool flag = true;
            if (Abs(X - pt.X) >= precision)
            {
                flag = false;
                return flag;
            }
            if (Abs(Y - pt.Y) >= precision)
            {
                flag = false;
                return flag;
            }
            if (Abs(Z - pt.Z) >= precision)
            {
                flag = false;
                return flag;
            }
            return flag;
        }
        /// <summary>
        /// 获取或设置点的X坐标
        /// </summary>
        /// <value>获取或设置点的X坐标</value>
        public double X { get; set; }
        /// <summary>
        /// 获取或设置点的Y坐标
        /// </summary>
        /// <value>获取或设置点的Y坐标</value>
        public double Y { get; set; }
        /// <summary>
        /// 获取或设置点的Z坐标
        /// </summary>
        /// <value>获取或设置点的Z坐标</value>
        public double Z { get; set; }
        #region  运算符重载
        /// <summary>
        /// 点与向量的加法（点的移动）
        /// </summary>
        /// <param name="pt">所要移动的点</param>
        /// <param name="v">位移向量</param>
        /// <returns>所移动到的点</returns>
        public static Point operator +(Point pt, Vector v)
        { return new Point(pt.X + v.X, pt.Y + v.Y, pt.Z + v.Z); }
        /// <summary>
        /// 点与向量的减法
        /// </summary>
        /// <param name="pt1">点</param>
        /// <param name="v1">向量</param>
        /// <returns>差</returns>
        public static Point operator -(Point pt1, Vector v1)
        { return new Point(pt1.X - v1.X, pt1.Y - v1.Y, pt1.Z - v1.Z); }
        /// <summary>
        /// 两点的减法
        /// </summary>
        /// <param name="startPt">起点</param>
        /// <param name="endPt">终点</param>
        /// <returns>两点的差向量</returns>
        public static Vector operator -(Point startPt, Point endPt)
        { return new Vector(endPt.X - startPt.X, endPt.Y - startPt.Y, endPt.Z - startPt.Z); }
        #endregion
        /// <summary>
        /// 用旋转矩阵对点进行旋转
        /// </summary>
        /// <param name="roMatrix">旋转矩阵</param>
        /// <returns>旋转后的点位</returns>
        /// <exception cref="MatrixDimensionException">如果旋转矩阵的维数不对，则抛出异常。</exception>
        public Point TransformBy(Matrix roMatrix)
        { return Matrix.Trans(this, roMatrix); }
        /// <summary>
        /// 用四元数对点进行旋转
        /// </summary>
        /// <param name="qt">旋转使用的四元数</param>
        /// <returns>旋转后的点位</returns>
        public Point TransformBy(Quaternion qt)
        { return Quaternion.Rotation(this, qt); }
    }
}
